package com.lagou.edu.factory;

import com.lagou.edu.annotation.Autowired;
import com.lagou.edu.annotation.Repository;
import com.lagou.edu.annotation.Service;
import com.lagou.edu.annotation.Transactional;
import com.lagou.edu.utils.ClassUtil;
import com.lagou.edu.utils.ProxyFactory;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author 应癫
 *
 * 工厂类，生产对象（使用反射技术）
 */
public class AnnotationBeanFactory {

    /**
     * 任务一：读取解析xml，通过反射技术实例化对象并且存储待用（map集合）
     * 任务二：对外提供获取实例对象的接口（根据id获取）
     */

    private static Map<String,Object> map = new HashMap<>();  // 存储对象


    static {

        List<Class<?>> utils = ClassUtil.getClasses("com.lagou.edu.utils");
        List<Class<?>> daos = ClassUtil.getClasses("com.lagou.edu.dao");
        List<Class<?>> services = ClassUtil.getClasses("com.lagou.edu.service");
        List<Class<?>> classes = new ArrayList<>();
        classes.addAll(utils);
        classes.addAll(daos);
        classes.addAll(services);


        try {
            for (Class<?> aClass : classes) {
                Repository repository = aClass.getAnnotation(Repository.class);
                if (repository != null){
                    Object obj = aClass.newInstance();
                    map.put(aClass.getName(),obj);
                    Class<?>[] interfaces = aClass.getInterfaces();
                    for (Class<?> anInterface : interfaces) {
                        map.put(anInterface.getName(),obj);
                    }
                    if (null != repository.value() && !"".equals(repository.value())){
                        map.put(repository.value(),obj);
                    }
                }
                Service service = aClass.getAnnotation(Service.class);
                if (service != null){
                    Object obj = aClass.newInstance();
                    map.put(aClass.getName(),obj);
                    Class<?>[] interfaces = aClass.getInterfaces();
                    for (Class<?> anInterface : interfaces) {
                        map.put(anInterface.getName(),obj);
                    }
                    if (null != service.value() && !"".equals(service.value())){
                        map.put(service.value(),obj);
                    }
                }
            }

            for (Map.Entry<String, Object> stringObjectEntry : map.entrySet()) {
                // 遍历父对象中的所有方法，找到"set" + name
                Class<?> aClass = stringObjectEntry.getValue().getClass();
                Field[] fields = aClass.getDeclaredFields();
                for (Field field : fields) {
                    Autowired annotation = field.getAnnotation(Autowired.class);
                    if (annotation != null){
                        String name = field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
                        Method method = aClass.getMethod("set" + name, field.getType());
                        method.invoke(stringObjectEntry.getValue(),map.get(field.getType().getName()));
                    }
                }
            }

        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    public static  Object getBean(String id) {
        ProxyFactory proxyFactory = (ProxyFactory) map.get("com.lagou.edu.utils.ProxyFactory");
        Object object = map.get(id);
        Transactional annotation = object.getClass().getAnnotation(Transactional.class);
        if (annotation != null){
            Class<?>[] interfaces = object.getClass().getInterfaces();
            if (interfaces != null && interfaces.length > 0){
                return proxyFactory.getJdkProxy(object);
            } else {
                return proxyFactory.getCglibProxy(object);
            }
        }
        return object;
    }

    public static void main(String[] args) {
        Object bean = getBean("com.lagou.edu.service.TransferService");
        System.out.println(bean.toString());
    }


}
